using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Net;
using System.Threading;
using System.Xml;

namespace cb0tServer
{
    class ISPTrace
    {
        private Thread thread;
        private bool busy = false;

        private ushort vroom = 0;
        private String query = null;
        private String name = null;

        public void Query(ushort vroom, UserObject query)
        {
            if (busy)
            {
                UserPool.Broadcast(vroom, ServerOutboundPackets.AnnoucePacket("wait a few seconds and then try again"));
                return;
            }

            this.vroom = vroom;
            this.query = query.physical_ip.ToString();
            this.name = query.name;
            this.thread = new Thread(new ThreadStart(this.Work));
            this.thread.Start();
        }

        public void QueryByIP(ushort vroom, String ip)
        {
            if (busy)
            {
                UserPool.Broadcast(vroom, ServerOutboundPackets.AnnoucePacket("wait a few seconds and then try again"));
                return;
            }

            this.vroom = vroom;
            this.query = ip;
            this.name = ip;
            this.thread = new Thread(new ThreadStart(this.Work));
            this.thread.Start();
        }

        private void Work()
        {
            this.busy = true;

            try
            {
                WebRequest request = WebRequest.Create("http://chatrooms.marsproject.net/geo/?q=" + this.query);
                WebResponse response = request.GetResponse();
                Stream stream = response.GetResponseStream();
                StreamReader reader = new StreamReader(stream, Encoding.Default);
                String[] lines = reader.ReadToEnd().Split(new String[] { "\n" }, StringSplitOptions.None);

                TraceObject obj = new TraceObject();
                obj.country = lines[0];
                obj.region = lines[1];
                obj.city = lines[2];
                obj.SetTime(lines[3], lines[4]);

                reader.Close();
                stream.Flush();
                stream.Close();
                response.Close();

                UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("\x000310\x0007Trace Result for: " + this.name));
                UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket(" "));

                bool color1 = true;

                if (obj.country.Length > 0)
                {
                    UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("\x00030" + (color1 ? "6" : "3") + "Country: " + obj.country));
                    color1 = !color1;
                }

                if (obj.region.Length > 0)
                {
                    UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("\x00030" + (color1 ? "6" : "3") + "Region: " + obj.region));
                    color1 = !color1;
                }

                if (obj.city.Length > 0)
                {
                    UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("\x00030" + (color1 ? "6" : "3") + "City: " + obj.city));
                    color1 = !color1;
                }

                if (obj.got_time)
                {
                    UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("\x00030" + (color1 ? "6" : "3") + "Local Time: " + obj.localtime));
                    color1 = !color1;
                }

                UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket(" "));
                UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("\x000310\x0007Trace Complete"));
            }
            catch
            {
                UserPool.Broadcast(this.vroom, ServerOutboundPackets.AnnoucePacket("Unable to trace a result for " + this.name));
            }

            this.busy = false;
        }
    }

    class TraceObject
    {
        public String city = null;
        public String region = null;
        public String country = null;
        public int offset = 0;
        public bool dst = false;
        public bool got_time = false;

        public void SetTime(String _lat, String _lon)
        {
            float lat, lon;

            if (!float.TryParse(_lat, out lat))
                return;

            if (!float.TryParse(_lon, out lon))
                return;

            got_time = true;

            DateTime d = DateTime.UtcNow;

            if (lat > 15) // northern hemisphere
                if (d.Month > 3 && d.Month < 11)
                    this.dst = true;

            if (lat < -15) // southern hemisphere
                if (d.Month > 9 || d.Month < 4)
                    this.dst = true;

            this.offset = (int)(lon / 15);

            if (lon > 0)
                this.offset += 1;

            this.offset *= 3600; // to seconds
        }

        public String localtime
        {
            get
            {
                DateTime d = DateTime.UtcNow.AddSeconds(offset);

                if (this.dst)
                    d = d.AddHours(1);

                int h = d.Hour;
                int m = d.Minute;
                bool am = true;

                if (h > 11)
                    am = !am;

                if (h > 12)
                    h -= 12;

                if (h == 0)
                    h += 12;

                return h + ":" + (m < 10 ? ("0" + m) : m.ToString()) + " " + (am ? "AM" : "PM");
            }
        }
    }
}
